package model.extras;

import java.io.IOException;
import java.util.ArrayList;

import model.archivo.ArchivoDiccionario;
import model.registro.RegistroIndicePesoGlobal;
import model.registro.RegistroOrdAparicion;

public class SortExterno {
		  /**
	     * Mergesort 
	     * @param  archOrdAparicion es array de registros de aparicion
	     * @param  archPeso es array de registros de peso
		 * @throws IOException 
	     **/
	    public static void mergeSort( ArchivoDiccionario archOrdAparicion, ArchivoDiccionario archPesos, ArchivoDiccionario archSalida ) throws IOException {
	    	
	    	ArrayList<RegistroIndicePesoGlobal> pesosList = new ArrayList<RegistroIndicePesoGlobal>();
	    	ArrayList<RegistroOrdAparicion> ordAparicionList = new ArrayList<RegistroOrdAparicion>();
	    	archOrdAparicion.rwArchivo();
			archPesos.rwArchivo();
	    	int offset = 0;
			float frecuenciaLocal;
			
			
			while (offset != archOrdAparicion.getOffSetEOF()) {
				RegistroOrdAparicion regAux = new RegistroOrdAparicion();
			    archOrdAparicion.leerRegistro(regAux);
			   // System.out.println("se levanta del disco "+regAux.getNroAparicion());
			    ordAparicionList.add(regAux);
			    offset =  (int)archOrdAparicion.getFilePointer();
			}
			RegistroOrdAparicion[] listaAux = new RegistroOrdAparicion[ordAparicionList.size()];
			//pasar el archivo de pesos a lista pesos
			offset = 0;
			while (offset != archPesos.getOffSetEOF()) {
				RegistroIndicePesoGlobal regAux2 = new RegistroIndicePesoGlobal();
			    archPesos.leerRegistro(regAux2);
			   // System.out.println("se levanta del disco "+regAux.getNroAparicion());
			    pesosList.add(regAux2);
			    offset =  (int)archPesos.getFilePointer();
			}
			//
			archSalida.rwArchivo();
	    	for (int i = 0; i < ordAparicionList.size(); i++) {
	    		RegistroOrdAparicion regAux = new RegistroOrdAparicion();
				regAux = ordAparicionList.get(i);
				frecuenciaLocal= regAux.getRepeticiones()/regAux.getCantTerminosDoc();
				regAux.setRepeticiones(frecuenciaLocal);
			for (RegistroIndicePesoGlobal reg : pesosList)
				if (reg.getNroAparicion()== regAux.getNroAparicion()){
					//recordar que en el offset guardo el numero de aparicion
					regAux.setPesoGlobal(reg.getPesoGlobal());
				}
			listaAux[i] = regAux;
		}
		
	    	RegistroOrdAparicion [] tmpArray = new RegistroOrdAparicion[ listaAux.length ];
	        mergeSort( listaAux, tmpArray, 0, listaAux.length - 1 );
	        //pasar la lista Aux a Disco de nuevo
	        for (int i = 0; i < listaAux.length; i++) {
	        	archSalida.escribirRegistro(listaAux[i]);
			}
	    }

	    /**
	     * metodo interno para llamados recursivos
	     * @param a el array de elementos comparables
	     * @param tmpArray array temp para resultados temporales
	     * @param left limite izquierdo.
	     * @param right limite derecho.
	     */
	    private static void mergeSort( RegistroOrdAparicion [ ] a, RegistroOrdAparicion [ ] tmpArray,
	            int left, int right ) {
	        if( left < right ) {
	            int center = ( left + right ) / 2;
	            mergeSort( a, tmpArray, left, center );
	            mergeSort( a, tmpArray, center + 1, right );
	            merge( a, tmpArray, left, center + 1, right );
	        }
	    }

	    /**
	     * metodo q hace el merge de 2 subarrays ya ordenados.
	     * @param a array de elementos comparables
	     * @param tmpArray array temporal de resultados temporales.
	     * @param leftPos lim izquierdo.
	     * @param rightPos comienzo del 2do array.
	     * @param rightEnd limite dereccho.
	     */
	    private static void merge( RegistroOrdAparicion [ ] a, RegistroOrdAparicion [ ] tmpArray,
	            int leftPos, int rightPos, int rightEnd ) {
	        int leftEnd = rightPos - 1;
	        int tmpPos = leftPos;
	        int numElements = rightEnd - leftPos + 1;

	        while( leftPos <= leftEnd && rightPos <= rightEnd )
	            if( a[leftPos].compareTo(a[rightPos] ) <= 0 ) {
					tmpArray[ tmpPos++ ] = a[ leftPos++ ];
				} else {
					tmpArray[ tmpPos++ ] = a[ rightPos++ ];
				}

	        while( leftPos <= leftEnd )    // Copy rest of first half
	            tmpArray[ tmpPos++ ] = a[ leftPos++ ];

	        while( rightPos <= rightEnd )  // Copy rest of right half
	            tmpArray[ tmpPos++ ] = a[ rightPos++ ];

	        
	        for( int i = 0; i < numElements; i++, rightEnd-- )
	            a[ rightEnd ] = tmpArray[ rightEnd ];
	    }


	}

